#include<stdio.h>
#include<stdlib.h>
#include<Mesh_IO/Mesh_IO.h>
#include<Mesh/libcell_iterator.h>
#include<tool/libcell_tools_octree.h>
#include<tool/libcell_octree_iterator.h>
#include<Algorithm/points_cloud_algorithm.h>

#include<libcell_macros.h>
#include<time.h>
#include<thread>
//输入八叉树的某个结点，对它以下的所有含有顶点(只要包含顶点就会划分)的体素划分一次
//返回划分后含有顶点的体素个数

int my_oc_node_divide_all_leaves(OC_Node* ocn)
{
    int re=0;
    if(ocn==NULL)
    {return re;}
    if(ocn->children[0]==NULL)
    {
        int sum=node_size((Node*)(ocn->value));
        if(sum>=1)
        {return  oc_node_divide_one_leaf(ocn);}
        else
        {return 0;}
    }
    for(int i=0;i<8;i++)
    {
        re+=my_oc_node_divide_all_leaves(ocn->children[i]);
    }
    return re;
}

OC_Node* my_get_ocn_depth_and_one_leaf(OC_Node*ocn,int *depth)
{
    *depth=0;
    OC_Node* re=NULL;
    if(ocn->children[0]==NULL)
    {
        if(ocn->value==NULL)
        {return NULL;}
        else
        {
            *depth=1;
            return ocn;
        }
    }
    else
    {
        for(int i=0;i<8;i++)
        {
            int depth1=0;
            re=my_get_ocn_depth_and_one_leaf(ocn->children[i],&depth1); 
            if(re!=NULL)
            {
                *depth=1+depth1;
                return re;
            }
        }
    }
    return re;
}
void test_read_obj()
{
    Mesh mesh;
    Mesh_init(&mesh);

    _ReadObj_(&mesh,"cat.obj");

    Mesh_free(&mesh);

}
// static inline void oc_node_divide_all_leavest(OC_Node* ocn,int *count)
// {
//     *count=oc_node_divide_all_leaves(ocn);
// }


// //加入线程

// int oc_node_divide_all_leavesp(OC_Node* ocn)
// {
//     int re=0;
//     if(ocn==NULL)
//     {return re;}
//     if(ocn->children[0]==NULL)
//     {
//         return (ocn->value==NULL?0:oc_node_divide_one_leaf(ocn));
//     }

//     int counts[8]={0};
//     std::thread mythread0(oc_node_divide_all_leavest,ocn->children[0],&(counts[0]));
//     std::thread mythread1(oc_node_divide_all_leavest,ocn->children[1],&(counts[1]));
//     std::thread mythread2(oc_node_divide_all_leavest,ocn->children[2],&(counts[2]));
//     std::thread mythread3(oc_node_divide_all_leavest,ocn->children[3],&(counts[3]));
//     std::thread mythread4(oc_node_divide_all_leavest,ocn->children[4],&(counts[4]));
//     std::thread mythread5(oc_node_divide_all_leavest,ocn->children[5],&(counts[5]));
//     std::thread mythread6(oc_node_divide_all_leavest,ocn->children[6],&(counts[6]));
//     std::thread mythread7(oc_node_divide_all_leavest,ocn->children[7],&(counts[7]));


//     mythread0.join();
//     mythread1.join();
//     mythread2.join();
//     mythread3.join();
//     mythread4.join();
//     mythread5.join();
//     mythread6.join();
//     mythread7.join();
//     for(int i=0;i<8;i++)
//     {
//         re+=counts[i];
//     }
//     return re;  

// }

void test_ocn()
{

    Mesh mesh;
    Mesh_init(&mesh);

    _ReadPly_(&mesh,"test4.ply");
    OC_Node* ocn=(OC_Node*)malloc(sizeof(OC_Node));
    Node* node=NULL;
    for(auto vit=mesh.v_begin(&mesh);vit!=mesh.v_end(&mesh);vit++)
    {
        node=node_overlying(node,quote(vit));
    }


    clock_t t=clock();

    time_t t1=time(0);
    Node* vertices1=downsampling_through_size(node,8.334);
    //printf("time si %.5f \n",(double)(clock()-t)/CLOCKS_PER_SEC );
    time_t t3=time(0);
    printf("time %ld\n",t3-t1);

    t=clock();
    oc_node_init_from_node(ocn,node); 

    for(int i=0;i<5;i++)
    {
        oc_node_divide_all_leaves(ocn); 
    }

    printf("time si %.5f \n",(double)(clock()-t)/CLOCKS_PER_SEC );
    //t=clock();
    for(int i=0;i<3;i++)
    {
        //oc_node_divide_all_leaves(ocn); 
        oc_node_divide_all_leavesp(ocn);
    }
    //oc_node_divide_all_leavesp(ocn);
    //oc_node_divide_all_leaves(ocn);
    time_t t2=time(0);
    printf("time %ld\n",t2-t3);


    //printf("time si %.5f \n",(double)(clock()-t)/CLOCKS_PER_SEC );

    Mesh_free(&mesh); 
}
int main()
{
    test_ocn();
    Mesh mesh;
    Mesh_init(&mesh);
    mesh.dimension=0;
    double p[3]={0,0,0};
    template_v* v=mesh.create_vertexv(&mesh,p,3);
    p[0]=1;p[1]=0;p[2]=0;
    mesh.create_vertexv(&mesh,p,3);
    p[0]=0;p[1]=1;p[2]=0;
    mesh.create_vertexv(&mesh,p,3);
    p[0]=0;p[1]=0;p[2]=1;
    mesh.create_vertexv(&mesh,p,3);
    p[0]=1.001;p[1]=0.001;p[2]=0;
    mesh.create_vertexv(&mesh,p,3);


    OC_Node* ocn=(OC_Node*)malloc(sizeof(OC_Node));
    Node* node=NULL;
    for(auto vit=mesh.v_begin(&mesh);vit!=mesh.v_end(&mesh);vit++)
    {
        node=node_overlying(node,quote(vit));
    }

    oc_node_init_from_node(ocn,node);

    printf("vexel size:%d vertices size:%d\n",oc_node_voxel_size(ocn),oc_node_vertices_size(ocn));
    
    for(int i=0;i<10;i++)
    {
        my_oc_node_divide_all_leaves(ocn);

        int depth=0;
        OC_Node* ocn1= my_get_ocn_depth_and_one_leaf(ocn,&depth);
        printf("depth: %d\n %lf %lf %lf %lf %lf %lf\n",depth,ocn1->loc_min[0],ocn1->loc_min[1],ocn1->loc_min[2],
            ocn1->loc_max[0],ocn1->loc_max[1],ocn1->loc_max[2]); 
        printf("vexel size:%d vertices size:%d\n",oc_node_voxel_size(ocn),oc_node_vertices_size(ocn));   
    }




    Mesh_free(&mesh);

    test_read_obj();

    printf("end\n");
    return 0;
}
